home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume25 / finger / part06 < prev    next >
Encoding:
Text File  |  1992-04-04  |  58.1 KB  |  2,179 lines

  1. Newsgroups: comp.sources.unix
  2. From: phil@Shiva.COM (Phil Budne)
  3. Subject: v25i169: finger - Phil's Finger Program, Part06/07
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: phil@Shiva.COM (Phil Budne)
  8. Posting-Number: Volume 25, Issue 169
  9. Archive-Name: finger/part06
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 6 (of 7)."
  18. # Contents:  COPYING finger.c fingerd.c getcommand.c
  19. # Wrapped by budd@bu-it on Fri Jul  6 13:22:06 1990
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f COPYING -a "${1}" != "-c" ; then 
  22.   echo shar: Will not over-write existing file \"COPYING\"
  23. else
  24. echo shar: Extracting \"COPYING\" \(12042 characters\)
  25. sed "s/^X//" >COPYING <<'END_OF_COPYING'
  26. X            GNU GENERAL PUBLIC LICENSE
  27. X             Version 1, February 1989
  28. X
  29. X Copyright (C) 1989 Free Software Foundation, Inc.
  30. X                    675 Mass Ave, Cambridge, MA 02139, USA
  31. X Everyone is permitted to copy and distribute verbatim copies
  32. X of this license document, but changing it is not allowed.
  33. X
  34. X                Preamble
  35. X
  36. X  The license agreements of most software companies try to keep users
  37. Xat the mercy of those companies.  By contrast, our General Public
  38. XLicense is intended to guarantee your freedom to share and change free
  39. Xsoftware--to make sure the software is free for all its users.  The
  40. XGeneral Public License applies to the Free Software Foundation's
  41. Xsoftware and to any other program whose authors commit to using it.
  42. XYou can use it for your programs, too.
  43. X
  44. X  When we speak of free software, we are referring to freedom, not
  45. Xprice.  Specifically, the General Public License is designed to make
  46. Xsure that you have the freedom to give away or sell copies of free
  47. Xsoftware, that you receive source code or can get it if you want it,
  48. Xthat you can change the software or use pieces of it in new free
  49. Xprograms; and that you know you can do these things.
  50. X
  51. X  To protect your rights, we need to make restrictions that forbid
  52. Xanyone to deny you these rights or to ask you to surrender the rights.
  53. XThese restrictions translate to certain responsibilities for you if you
  54. Xdistribute copies of the software, or if you modify it.
  55. X
  56. X  For example, if you distribute copies of a such a program, whether
  57. Xgratis or for a fee, you must give the recipients all the rights that
  58. Xyou have.  You must make sure that they, too, receive or can get the
  59. Xsource code.  And you must tell them their rights.
  60. X
  61. X  We protect your rights with two steps: (1) copyright the software, and
  62. X(2) offer you this license which gives you legal permission to copy,
  63. Xdistribute and/or modify the software.
  64. X
  65. X  Also, for each author's protection and ours, we want to make certain
  66. Xthat everyone understands that there is no warranty for this free
  67. Xsoftware.  If the software is modified by someone else and passed on, we
  68. Xwant its recipients to know that what they have is not the original, so
  69. Xthat any problems introduced by others will not reflect on the original
  70. Xauthors' reputations.
  71. X
  72. X  The precise terms and conditions for copying, distribution and
  73. Xmodification follow.
  74. X
  75. X            GNU GENERAL PUBLIC LICENSE
  76. X   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  77. X
  78. X  0. This License Agreement applies to any program or other work which
  79. Xcontains a notice placed by the copyright holder saying it may be
  80. Xdistributed under the terms of this General Public License.  The
  81. X"Program", below, refers to any such program or work, and a "work based
  82. Xon the Program" means either the Program or any work containing the
  83. XProgram or a portion of it, either verbatim or with modifications.  Each
  84. Xlicensee is addressed as "you".
  85. X
  86. X  1. You may copy and distribute verbatim copies of the Program's source
  87. Xcode as you receive it, in any medium, provided that you conspicuously and
  88. Xappropriately publish on each copy an appropriate copyright notice and
  89. Xdisclaimer of warranty; keep intact all the notices that refer to this
  90. XGeneral Public License and to the absence of any warranty; and give any
  91. Xother recipients of the Program a copy of this General Public License
  92. Xalong with the Program.  You may charge a fee for the physical act of
  93. Xtransferring a copy.
  94. X
  95. X  2. You may modify your copy or copies of the Program or any portion of
  96. Xit, and copy and distribute such modifications under the terms of Paragraph
  97. X1 above, provided that you also do the following:
  98. X
  99. X    a) cause the modified files to carry prominent notices stating that
  100. X    you changed the files and the date of any change; and
  101. X
  102. X    b) cause the whole of any work that you distribute or publish, that
  103. X    in whole or in part contains the Program or any part thereof, either
  104. X    with or without modifications, to be licensed at no charge to all
  105. X    third parties under the terms of this General Public License (except
  106. X    that you may choose to grant warranty protection to some or all
  107. X    third parties, at your option).
  108. X
  109. X    c) If the modified program normally reads commands interactively when
  110. X    run, you must cause it, when started running for such interactive use
  111. X    in the simplest and most usual way, to print or display an
  112. X    announcement including an appropriate copyright notice and a notice
  113. X    that there is no warranty (or else, saying that you provide a
  114. X    warranty) and that users may redistribute the program under these
  115. X    conditions, and telling the user how to view a copy of this General
  116. X    Public License.
  117. X
  118. X    d) You may charge a fee for the physical act of transferring a
  119. X    copy, and you may at your option offer warranty protection in
  120. X    exchange for a fee.
  121. X
  122. XMere aggregation of another independent work with the Program (or its
  123. Xderivative) on a volume of a storage or distribution medium does not bring
  124. Xthe other work under the scope of these terms.
  125. X
  126. X  3. You may copy and distribute the Program (or a portion or derivative of
  127. Xit, under Paragraph 2) in object code or executable form under the terms of
  128. XParagraphs 1 and 2 above provided that you also do one of the following:
  129. X
  130. X    a) accompany it with the complete corresponding machine-readable
  131. X    source code, which must be distributed under the terms of
  132. X    Paragraphs 1 and 2 above; or,
  133. X
  134. X    b) accompany it with a written offer, valid for at least three
  135. X    years, to give any third party free (except for a nominal charge
  136. X    for the cost of distribution) a complete machine-readable copy of the
  137. X    corresponding source code, to be distributed under the terms of
  138. X    Paragraphs 1 and 2 above; or,
  139. X
  140. X    c) accompany it with the information you received as to where the
  141. X    corresponding source code may be obtained.  (This alternative is
  142. X    allowed only for noncommercial distribution and only if you
  143. X    received the program in object code or executable form alone.)
  144. X
  145. XSource code for a work means the preferred form of the work for making
  146. Xmodifications to it.  For an executable file, complete source code means
  147. Xall the source code for all modules it contains; but, as a special
  148. Xexception, it need not include source code for modules which are standard
  149. Xlibraries that accompany the operating system on which the executable
  150. Xfile runs, or for standard header files or definitions files that
  151. Xaccompany that operating system.
  152. X
  153. X  4. You may not copy, modify, sublicense, distribute or transfer the
  154. XProgram except as expressly provided under this General Public License.
  155. XAny attempt otherwise to copy, modify, sublicense, distribute or transfer
  156. Xthe Program is void, and will automatically terminate your rights to use
  157. Xthe Program under this License.  However, parties who have received
  158. Xcopies, or rights to use copies, from you under this General Public
  159. XLicense will not have their licenses terminated so long as such parties
  160. Xremain in full compliance.
  161. X
  162. X  5. By copying, distributing or modifying the Program (or any work based
  163. Xon the Program) you indicate your acceptance of this license to do so,
  164. Xand all its terms and conditions.
  165. X
  166. X  6. Each time you redistribute the Program (or any work based on the
  167. XProgram), the recipient automatically receives a license from the original
  168. Xlicensor to copy, distribute or modify the Program subject to these
  169. Xterms and conditions.  You may not impose any further restrictions on the
  170. Xrecipients' exercise of the rights granted herein.
  171. X
  172. X  7. The Free Software Foundation may publish revised and/or new versions
  173. Xof the General Public License from time to time.  Such new versions will
  174. Xbe similar in spirit to the present version, but may differ in detail to
  175. Xaddress new problems or concerns.
  176. X
  177. XEach version is given a distinguishing version number.  If the Program
  178. Xspecifies a version number of the license which applies to it and "any
  179. Xlater version", you have the option of following the terms and conditions
  180. Xeither of that version or of any later version published by the Free
  181. XSoftware Foundation.  If the Program does not specify a version number of
  182. Xthe license, you may choose any version ever published by the Free Software
  183. XFoundation.
  184. X
  185. X  8. If you wish to incorporate parts of the Program into other free
  186. Xprograms whose distribution conditions are different, write to the author
  187. Xto ask for permission.  For software which is copyrighted by the Free
  188. XSoftware Foundation, write to the Free Software Foundation; we sometimes
  189. Xmake exceptions for this.  Our decision will be guided by the two goals
  190. Xof preserving the free status of all derivatives of our free software and
  191. Xof promoting the sharing and reuse of software generally.
  192. X
  193. X                NO WARRANTY
  194. X
  195. X  9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
  196. XFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
  197. XOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
  198. XPROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
  199. XOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  200. XMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
  201. XTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
  202. XPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
  203. XREPAIR OR CORRECTION.
  204. X
  205. X  10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
  206. XWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
  207. XREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
  208. XINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
  209. XOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
  210. XTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
  211. XYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
  212. XPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
  213. XPOSSIBILITY OF SUCH DAMAGES.
  214. X
  215. X             END OF TERMS AND CONDITIONS
  216. X
  217. X    Appendix: How to Apply These Terms to Your New Programs
  218. X
  219. X  If you develop a new program, and you want it to be of the greatest
  220. Xpossible use to humanity, the best way to achieve this is to make it
  221. Xfree software which everyone can redistribute and change under these
  222. Xterms.
  223. X
  224. X  To do so, attach the following notices to the program.  It is safest to
  225. Xattach them to the start of each source file to most effectively convey
  226. Xthe exclusion of warranty; and each file should have at least the
  227. X"copyright" line and a pointer to where the full notice is found.
  228. X
  229. X    <one line to give the program's name and a brief idea of what it does.>
  230. X    Copyright (C) 19yy  <name of author>
  231. X
  232. X    This program is free software; you can redistribute it and/or modify
  233. X    it under the terms of the GNU General Public License as published by
  234. X    the Free Software Foundation; either version 1, or (at your option)
  235. X    any later version.
  236. X
  237. X
  238. XAlso add information on how to contact you by electronic and paper mail.
  239. X
  240. XIf the program is interactive, make it output a short notice like this
  241. Xwhen it starts in an interactive mode:
  242. X
  243. X    Gnomovision version 69, Copyright (C) 19xx name of author
  244. X    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
  245. X    This is free software, and you are welcome to redistribute it
  246. X    under certain conditions; type `show c' for details.
  247. X
  248. XThe hypothetical commands `show w' and `show c' should show the
  249. Xappropriate parts of the General Public License.  Of course, the
  250. Xcommands you use may be called something other than `show w' and `show
  251. Xc'; they could even be mouse-clicks or menu items--whatever suits your
  252. Xprogram.
  253. X
  254. XYou should also get your employer (if you work as a programmer) or your
  255. Xschool, if any, to sign a "copyright disclaimer" for the program, if
  256. Xnecessary.  Here a sample; alter the names:
  257. X
  258. X  Yoyodyne, Inc., hereby disclaims all copyright interest in the
  259. X  program `Gnomovision' (a program to direct compilers to make passes
  260. X  at assemblers) written by James Hacker.
  261. X
  262. X  <signature of Ty Coon>, 1 April 1989
  263. X  Ty Coon, President of Vice
  264. X
  265. XThat's all there is to it!
  266. X
  267. X
  268. END_OF_COPYING
  269. if test 12042 -ne `wc -c <COPYING`; then
  270.     echo shar: \"COPYING\" unpacked with wrong size!
  271. fi
  272. # end of overwriting check
  273. fi
  274. if test -f finger.c -a "${1}" != "-c" ; then 
  275.   echo shar: Will not over-write existing file \"finger.c\"
  276. else
  277. echo shar: Extracting \"finger.c\" \(13818 characters\)
  278. sed "s/^X//" >finger.c <<'END_OF_finger.c'
  279. X/*
  280. X * finger.c -- output formatting for finger (main is in args.c)
  281. X *
  282. X * Copyright (C) 1986, 1990  Philip L. Budne
  283. X *
  284. X * This file is part of "Phil's Finger Program".
  285. X *
  286. X * This program is free software; you can redistribute it and/or modify
  287. X * it under the terms of the GNU General Public License as published by
  288. X * the Free Software Foundation; either version 1, or (at your option)
  289. X * any later version.
  290. X *
  291. X */
  292. X
  293. X# ifndef lint
  294. Xstatic char *rcsid = "$Id: finger.c,v 3.0 90/07/06 13:10:35 budd Rel $";
  295. X# endif /* lint not defined */
  296. X
  297. X# include <sys/types.h>
  298. X# include <stdio.h>
  299. X# include "person.h"
  300. X# include "output.h"
  301. X# include "args.h"            /* before luser.h */
  302. X# include "luser.h"
  303. X# include "finger.h"
  304. X# include "pr.h"
  305. X# include "inquire.h"            /* for INQUIRE */
  306. X# include "ttylocfile.h"
  307. X
  308. X# define PID_COL        /* display /pid in seperate column */
  309. X
  310. X/*# define RELATION            /* display REL if this is defined */
  311. X/*# define REL_SUP ""        /* (define as quoted string of relations */
  312. X                /*  to supress display of) */
  313. X
  314. XFORWARD LOCAL void
  315. X# ifdef RELATION
  316. X    prelation(),
  317. X# endif /* RELATION defined */
  318. X    pusername(), pgroup(), pspace(), ppname(),
  319. X    pcmd(), pidle(), pbiff(), ptty(), pmesg(), plocation(), ppid(),
  320. X    pstr(), pchar(), togoal();
  321. X
  322. XLOCAL int outcol, goalcol;
  323. X
  324. X# define USER_WID 8
  325. X# define PROG_WID 7            /* 6 prog + 1 flag */
  326. X
  327. X# ifndef TTY_WID
  328. X# ifdef AIX3
  329. X# define TTY_WID 6
  330. X# else  /* AIX3 not defined */
  331. X# if defined(UmaxV) || defined(PTS_PTY_NAMES)
  332. X# define TTY_WID 5            /* rtAAPPS or ptsNN */
  333. X# else  /* not defined(UmaxV) || defined(PTS_PTY_NAMES) */
  334. X# define TTY_WID 3
  335. X# endif /* not defined(UmaxV) || defined(PTS_PTY_NAMES) */
  336. X# endif /* AIX3 not defined */
  337. X# endif /* TTY_WID not defined */
  338. X
  339. X# define BASE_PER_WID (22+3+3)        /* base person width */
  340. X
  341. Xtypedef void (*FPTR)();
  342. X
  343. XFPTR fields[] = {
  344. X    pusername,
  345. X    pspace,
  346. X    pgroup,
  347. X# ifdef RELATION
  348. X# define GRPREL_WID 3            /* 2 + space */
  349. X    prelation,
  350. X# else  /* RELATION not defined */
  351. X# define GRPREL_WID 2            /* 1 + space */
  352. X# endif /* RELATION not defined */
  353. X    pspace,
  354. X    ppname,
  355. X    NULL
  356. X}; /* fields */
  357. X
  358. X# define PER_WID (BASE_PER_WID-TTY_WID-GRPREL_WID)
  359. X
  360. X
  361. XFPTR fields2[] = {
  362. X# ifdef PID_COL
  363. X    ppid,
  364. X# endif /* PID_COL defined */
  365. X# ifndef SUPPRESS_WHAT
  366. X    pcmd,
  367. X# endif /* SUPPRESS_WHAT not defined */
  368. X    pidle,
  369. X    pbiff,
  370. X    ptty,
  371. X    pmesg,
  372. X    plocation,
  373. X    NULL
  374. X}; /* fields2 */
  375. X
  376. X/* display when program running from another uid */
  377. X# ifndef SUID_ROOT
  378. X# define SUID_ROOT '+'
  379. X# endif /* SUID_ROOT not defined */
  380. X
  381. X# ifndef SUID_OTHER
  382. X# define SUID_OTHER '!'
  383. X# endif /* SUID_OTHER not defined */
  384. X
  385. X/* when no command found */
  386. X# ifndef EMPTY_CMD
  387. X# define EMPTY_CMD "??"
  388. X# endif /* EMPTY_CMD not defined */
  389. X
  390. X# define NO_GROUP ' '
  391. X
  392. X# ifdef RELATION
  393. X# define REL_HEADER 'R'
  394. X# define GRP_HEADER 'G'
  395. X# else  /* RELATION not defined */
  396. X# define GRP_HEADER ' '        /* or 'G' */
  397. X# endif /* RELATION not defined */
  398. X
  399. X/****** what to show when there is no person structure ******/
  400. X# define NO_RELATION ' '
  401. X
  402. X# ifdef INQUIRE
  403. X# define NO_NAME "--No inquire entry--"
  404. X# else  /* INQUIRE not defined */
  405. X# define NO_NAME "--No password entry--" /* acucntrl locks?!*/
  406. X# endif /* INQUIRE not defined */
  407. X
  408. Xextern LTREE *maketree();        /* from getent.c */
  409. Xextern struct pr *getcommand();        /* from getcommand.c */
  410. Xextern char *getttyloc();        /* from gettyloc.c */
  411. Xextern int pwtree();            /* from getperson.c */
  412. Xextern whois(), plan();            /* from whois.c */
  413. Xextern char *gtname(), *intstr();    /* from output.c */
  414. X
  415. XLOCAL time_t now;            /* current time */
  416. XLOCAL int personwidth;            /* calculated at runtime! */
  417. X
  418. XLOCAL void                /* forwards.. */
  419. X    finguser(),
  420. X    fingheader(),
  421. X    dogecos();
  422. X
  423. XGLOBAL void dofinger( t )
  424. XLTREE *t;
  425. X{
  426. X    int n;
  427. X
  428. X    personwidth = PER_WID;
  429. X# ifdef PID_COL
  430. X# define PID_WID 6
  431. X    if( sw_pid )
  432. X    personwidth -= PID_WID/2;
  433. X# endif /* PID_COL defined */
  434. X
  435. X# ifdef LASTLOG
  436. X    llopen();                /* open lastlog file */
  437. X# endif /* LASTLOG defined */
  438. X
  439. X    time( &now );            /* get current time */
  440. X    if( t == NULL )            /* nothing? */
  441. X    pwtree( (t = maketree()) );    /* get tree of all logged in users */
  442. X
  443. X    n = treesize( t );            /* count users */
  444. X    if( n == 0 )
  445. X    puts("No one logged in.");
  446. X    else {
  447. X# ifndef ALWAYS_PRINT_HEADER
  448. X    if( n > 1 )            /* be like oz finger */
  449. X# endif /* ALWAYS_PRINT_HEADER not defined */
  450. X        fingheader();        /* print header */
  451. X
  452. X    ptree( t, finguser );        /* print tree */
  453. X    } /* n != 0 */
  454. X
  455. X# ifdef LASTLOG
  456. X    llclose();                /* close lastlog file */
  457. X# endif /* LASTLOG defined */
  458. X} /* finger */
  459. X
  460. XLOCAL BOOL same;
  461. X
  462. XLOCAL void finguser(u)
  463. Xregister LUSER *u;
  464. X{
  465. X    static PERSON *person;
  466. X    static int incarnations;
  467. X    register FPTR *fp;
  468. X
  469. X    if( u->u_person != NULL ) {
  470. X    if( (u->u_person->p_flags & P_RC) != 0 ) { /* pw_gecos == "RC" ?*/
  471. X        dogecos( u );
  472. X        return;
  473. X    } /* RC hack */
  474. X    } /* run command */
  475. X
  476. X    if( u->u_flags & U_NLI ) {        /* not logged in */
  477. X    char location[ 50 ];
  478. X    time_t ltime;            /* last login time */
  479. X    int host;
  480. X    PERSON *p;
  481. X
  482. X    p = u->u_person;
  483. X    same = FALSE;            /* crock, pass as arg? *TODO* */
  484. X    for( fp = fields; *fp != NULL; fp++ )
  485. X        (*fp)( FALSE, u, p );
  486. X    goalcol++;            /* space */
  487. X
  488. X    /* get last login time from lastlog */
  489. X    if( p == NULL || (p->p_flags & P_NOPWENT) )
  490. X        pstr( "NO PASSWORD ENTRY (EXPIRED ACCOUNT?)" ); /* no pw ent? */
  491. X# ifdef LASTLOG
  492. X    else if( !lltime( p->p_uid, location, <ime, &host ) || ltime == 0 )
  493. X        pstr( "Login Unknown" );    /* no login time */
  494. X    else {                /* have login time. format it */
  495. X        int printed;
  496. X        TTYLOC *tp;
  497. X
  498. X        pstr( "Login " );
  499. X        pstr( nicetime( ltime ) );
  500. X
  501. X        /* TODO: if sw_its no "from...." */
  502. X        pstr( " from " );
  503. X        printed = FALSE;
  504. X        inittylocs();
  505. X        if( !host && (tp = findttyloc( location )) != NULL ) {
  506. X        char *s;
  507. X        if( tp->t_short != NULL )
  508. X            s = tp->t_short;
  509. X        else if( tp->t_locn != NULL )
  510. X            s = tp->t_locn;
  511. X        else
  512. X            s = NULL;
  513. X        if( s != NULL ) {
  514. X            printed = TRUE;
  515. X            pstr( s );
  516. X            pchar('{');
  517. X            pstr( location );
  518. X            pchar('}');
  519. X        }
  520. X        } /* foundttyloc */
  521. X        if( !printed )
  522. X        pstr( location );
  523. X    } /* have login time */
  524. X# endif /* LASTLOG defined */
  525. X    /* if sw_its check plan */
  526. X    pchar('\n');
  527. X    incarnations = 1;
  528. X    } /* not logged in */
  529. X    else {                /* is logged in */
  530. X    termstat( u );            /* get tty status (before getcommand) */
  531. X# ifndef SUPPRESS_WHAT
  532. X    getcommand( u );        /* get command/daemon procs */
  533. X# endif /* SUPPRESS_WHAT not defined */
  534. X
  535. X# ifndef NEVER_SAME
  536. X    if( u->u_person != NULL && u->u_person == person ) /* same person */
  537. X        same = TRUE;        /* as before? */
  538. X    else
  539. X# endif /* NEVER_SAME not defined */
  540. X        same = FALSE;
  541. X
  542. X    person = u->u_person;
  543. X    if( !same )
  544. X        if( person != NULL )
  545. X        incarnations = person->p_count;
  546. X        else
  547. X        incarnations = 1;
  548. X
  549. X    for( fp = fields; *fp != NULL; fp++ )
  550. X        (*fp)( FALSE, u, person );
  551. X    goalcol++;            /* blank space */
  552. X    for( fp = fields2; *fp != NULL; fp++ )
  553. X        (*fp)( FALSE, u, person );
  554. X    pchar( '\n' );
  555. X    } /* logged in */
  556. X
  557. X    if( incarnations-- == 1 ) {        /* final incarnation? */
  558. X    if( sw_whois ) {        /* do whois stuff */
  559. X        whois( u );
  560. X        blankline();
  561. X    }
  562. X
  563. X    if( u->u_sw.sw_mail || sw_whois || (u->u_flags & U_NLI) ) {
  564. X        mcheck( u );
  565. X        blankline();
  566. X    }
  567. X
  568. X    if( sw_whois ) {
  569. X        remarks( u );
  570. X        blankline();
  571. X    }
  572. X
  573. X    /*
  574. X     * show plan if asked for.  if user not logged in
  575. X     * show unless prohibited.
  576. X     */
  577. X    if( u->u_sw.sw_plan || (u->u_flags & U_NLI) && !u->u_sw.sw_noplan ) {
  578. X        plan( u );
  579. X        blankline();
  580. X    }
  581. X    } /* last incarnation */
  582. X} /* finguser */
  583. X
  584. XLOCAL void fingheader() {
  585. X    FPTR *fp;
  586. X
  587. X    for( fp = fields; *fp != NULL; fp++ )
  588. X    (*fp)( TRUE, NULL, NULL );
  589. X    goalcol++;                /* blank space */
  590. X    for( fp = fields2; *fp != NULL; fp++ )
  591. X    (*fp)( TRUE, NULL, NULL );
  592. X    pchar( '\n' );
  593. X    fflush(OUTPUT);
  594. X} /* fingheader */
  595. X
  596. XLOCAL void dogecos( u )            /* here if PNAME == "RC" */
  597. XLUSER *u;
  598. X{
  599. X    int pid, wpid;
  600. X
  601. X    pid = fork();            /* no vfork uses stdio */
  602. X    if( pid == 0 ) {            /* be childish */
  603. X    PERSON *p;
  604. X    p = u->u_person;
  605. X
  606. X    chdir(p->p_home);
  607. X    setuid(p->p_uid);
  608. X    setgid(p->p_gid);
  609. X    printf("%s/%s:\n", p->p_home, u->u_user);
  610. X    fflush( stdout );
  611. X    execl(u->u_user, u->u_user, 0);
  612. X    perror("Sorry");
  613. X    exit(1);
  614. X    }
  615. X    else if( pid < 0 )
  616. X    perror("fork");
  617. X
  618. X    while( (wpid = wait(0)) > 0 && wpid != pid ) /* lassie come home!! */
  619. X    ;
  620. X} /* dogecos */
  621. X
  622. XLOCAL void
  623. X_pchar( c )
  624. X    char c;
  625. X{
  626. X    static char linebuf[ 512 ], *lp = linebuf;
  627. X    if( c == '\n' ) {
  628. X    *lp = EOS;
  629. X    outline( linebuf );
  630. X    outcol = goalcol = 0;
  631. X    lp = linebuf;
  632. X    } /* newline */
  633. X    else {                /* not newline */
  634. X    if( c == '\t' )
  635. X        outcol = (outcol + 8) & ~7;
  636. X    else
  637. X        outcol++;
  638. X    *lp++ = c;
  639. X    } /* not newline */
  640. X} /* _pchar */
  641. X
  642. XLOCAL void
  643. Xtogoal() {
  644. X    while( outcol < goalcol ) {
  645. X    int temp;
  646. X    temp = (outcol + 8) & ~7;
  647. X    if( temp <= goalcol )
  648. X        _pchar( '\t' );
  649. X    else
  650. X        _pchar( ' ' );
  651. X    }
  652. X    goalcol = outcol;
  653. X} /* togoal */
  654. X
  655. XLOCAL void
  656. Xpchar( c )
  657. X    char c;
  658. X{
  659. X    if( outcol < goalcol )        /* save extra calls */
  660. X    togoal();
  661. X    _pchar( c );
  662. X} /* pchar */
  663. X
  664. XLOCAL void
  665. Xpstr( s )
  666. X    register char *s;
  667. X{
  668. X    if( s == NULL )
  669. X    return;
  670. X    togoal();
  671. X    while( *s )
  672. X    _pchar( *s++ );
  673. X} /* pstr */
  674. X
  675. XLOCAL void
  676. Xpcount( c, s )
  677. X    register c;
  678. X    register char *s;
  679. X{
  680. X    if( s == NULL )
  681. X    return;
  682. X    togoal();
  683. X    while( c-- && *s )
  684. X    _pchar( *s++ );
  685. X} /* pcount */
  686. X
  687. XLOCAL void
  688. Xpusername( title, u, p )
  689. X    BOOL title;
  690. X    LUSER *u;
  691. X    PERSON *p;
  692. X{
  693. X    if( title )
  694. X    pstr( "-User-" );
  695. X    else if( !same )
  696. X    pcount( USER_WID, u->u_user );
  697. X    goalcol += USER_WID;
  698. X} /* pusername */
  699. X
  700. X# ifdef INQUIRE
  701. X# ifdef RELATION
  702. XLOCAL void
  703. Xprelation( title, u, p )
  704. X    BOOL title;
  705. X    LUSER *u;
  706. X    PERSON *p;
  707. X{
  708. X    char rel;
  709. X    if( title )
  710. X    pchar( REL_HEADER );        /* title */
  711. X    else if( !same )            /* not same as last */
  712. X    if( p != NULL ) {        /* have person info */
  713. X        rel = p->p_relation;
  714. X# ifdef REL_SUP
  715. X        if( sw_whois || index(REL_SUP, rel) == NULL ) /* whois or */
  716. X# endif /* REL_SUP defined */
  717. X        pchar( rel );        /* not suppressed */
  718. X    } /* have person */
  719. X    else
  720. X        pchar( NO_REL );
  721. X    goalcol++;
  722. X} /* prelation */
  723. X# endif /* RELATION defined */
  724. X# endif /* INQUIRE defined */
  725. X
  726. XLOCAL void
  727. Xpgroup( title, u, p )
  728. X    BOOL title;
  729. X    LUSER *u;
  730. X    PERSON *p;
  731. X{
  732. X
  733. X    if( title )
  734. X    pchar( GRP_HEADER  );        /* title */
  735. X    else if( !same && p != NULL )    /* not same and have person */
  736. X    pchar( p->p_group );
  737. X
  738. X    goalcol++;
  739. X} /* pgroup */
  740. X
  741. XLOCAL void
  742. Xpspace( title, u, p )
  743. X    BOOL title;
  744. X    LUSER *u;
  745. X    PERSON *p;
  746. X{
  747. X    goalcol++;
  748. X} /* pspace */
  749. X
  750. XLOCAL void
  751. Xppname( title, u, p )
  752. X    BOOL title;
  753. X    LUSER *u;
  754. X    PERSON *p;
  755. X{
  756. X    if( title )
  757. X    pstr( "--Full name--" );
  758. X    else if( !same )
  759. X    if( p != NULL )
  760. X        pcount( personwidth, p->p_personal );
  761. X    else
  762. X        pstr( NO_NAME );
  763. X    goalcol += personwidth;
  764. X} /* ppname */
  765. X
  766. XLOCAL void
  767. Xpcmd( title, u, p )
  768. X    BOOL title;
  769. X    LUSER *u;
  770. X    PERSON *p;
  771. X{
  772. X    struct pr *pr;
  773. X
  774. X    if( title ) {
  775. X    pstr( (sw_its ? "Jobnam" : "-What-") );
  776. X    goalcol += PROG_WID;
  777. X    return;
  778. X    }
  779. X
  780. X    pr = u->u_command;
  781. X    if( pr != NULL ) {
  782. X    char suid;
  783. X
  784. X    if( p == NULL || pr->pr_uid == p->p_uid ) /* same uid? */
  785. X        suid = ' ';            /* no flag */
  786. X    else if( pr->pr_uid == 0 )    /* super user? */
  787. X        suid = SUID_ROOT;        /* flag it */
  788. X    else                /* someone else */
  789. X        suid = SUID_OTHER;
  790. X
  791. X    pcount( PROG_WID-1, pr->pr_cmd ); /* leave one for suid */
  792. X    pchar( suid );
  793. X    } /* pr not null */
  794. X    else
  795. X    pstr( EMPTY_CMD );
  796. X
  797. X    goalcol += PROG_WID;
  798. X} /* pcmd */
  799. X
  800. X# ifdef PID_COL
  801. XLOCAL void
  802. Xppid( title, u, p )
  803. X    BOOL title;
  804. X    LUSER *u;
  805. X    PERSON *p;
  806. X{
  807. X    if( !sw_pid )
  808. X    return;                /* takes no space!! */
  809. X
  810. X    if( title )
  811. X    pstr("  Pid");            /* two leading spaces */
  812. X    else if( u->u_command != NULL ) {
  813. X    char tbuf[10];
  814. X    sprintf(tbuf, "%5d", u->u_command->pr_pid );
  815. X    pstr( tbuf );
  816. X    }
  817. X    goalcol += PID_WID;            /* leave space after */
  818. X} /* ppid */
  819. X# endif /* PID_COL defined */
  820. X
  821. XLOCAL void
  822. Xpidle( title, u, p )
  823. X    BOOL title;
  824. X    LUSER *u;
  825. X    PERSON *p;
  826. X{
  827. X    if( title ) {
  828. X    if( sw_age )
  829. X        pstr( "-On-" );
  830. X    else if( sw_state )
  831. X        pstr( "Stat" );
  832. X# ifndef PID_COL
  833. X    else if( sw_pid )
  834. X        pstr( "  Pid" );        /* two spaces!! */
  835. X# endif /* PID_COL not defined */
  836. X    else
  837. X        pstr( "Idle" );
  838. X    } /* title */
  839. X    else {                /* real thing */
  840. X    char idbuf[ 100 ];
  841. X    strcpy( idbuf, "??" );
  842. X
  843. X    if( sw_age )
  844. X        intstr(idbuf, now - u->u_time ); /* get time on */
  845. X    else if( sw_state ) {
  846. X        if( u->u_command != NULL )
  847. X        getstate( idbuf, u->u_command ); /* get state */
  848. X    }
  849. X# ifndef PID_COL
  850. X    else if( sw_pid ) {
  851. X        if( u->u_command != NULL )
  852. X        sprintf(idbuf, "%5d", u->u_command->pr_pid );
  853. X    }
  854. X# endif /* PID_COL not defined */
  855. X    else if( u->u_flags & U_BADTTY )
  856. X        strcpy( idbuf, "*:**" );
  857. X    else
  858. X        intstr(idbuf, u->u_idle );    /* get idle time */
  859. X    pstr( idbuf );
  860. X    }
  861. X
  862. X# ifndef PID_COL
  863. X    if( sw_pid )            /* variable width!! */
  864. X    goalcol += 5;
  865. X    else
  866. X# endif /* PID_COL not defined */
  867. X    goalcol += 4;
  868. X} /* pidle */
  869. X
  870. XLOCAL void
  871. Xpbiff( title, u, p )
  872. X    BOOL title;
  873. X    LUSER *u;
  874. X    PERSON *p;
  875. X{
  876. X    /* alright, I lost control. C at its ugliest
  877. X     * nothing - space
  878. X     * biff    - dot
  879. X     * hungry  - comma
  880. X     * both    - semi
  881. X     */
  882. X    if( !title )
  883. X    pchar( " .,;"[ ((u->u_flags & U_BIFF)   ? 01 : 0) |
  884. X               ((u->u_flags & U_HUNGRY) ? 02 : 0) ] );
  885. X    goalcol++;
  886. X} /* pbiff */
  887. X
  888. XLOCAL void
  889. Xptty( title, u, p )
  890. X    BOOL title;
  891. X    LUSER *u;
  892. X    PERSON *p;
  893. X{
  894. X    if( title )
  895. X    pstr("TTY");
  896. X    else
  897. X    pcount( TTY_WID, gtname( u->u_line ) ); /* get trimmed tty name */
  898. X    goalcol += TTY_WID;
  899. X} /* ptty */
  900. X
  901. XLOCAL void
  902. Xpmesg( title, u, p )
  903. X    BOOL title;
  904. X    LUSER *u;
  905. X    PERSON *p;
  906. X{
  907. X    if( !title && (u->u_flags & U_NOWRITE) )
  908. X    pchar( '*' );
  909. X    goalcol++;
  910. X} /* pmesg */
  911. X
  912. XLOCAL void
  913. Xplocation( title, u, p )
  914. X    BOOL title;
  915. X    LUSER *u;
  916. X    PERSON *p;
  917. X{
  918. X    if( title )
  919. X    pstr( "-Console Location-" );
  920. X    else
  921. X    pstr( getttyloc( u ) );        /* tty location */
  922. X    /* no new goal!! */
  923. X} /* plocation */
  924. X
  925. X/*
  926. X * Local variables:
  927. X * comment-column: 40
  928. X * End:
  929. X */
  930. END_OF_finger.c
  931. if test 13818 -ne `wc -c <finger.c`; then
  932.     echo shar: \"finger.c\" unpacked with wrong size!
  933. fi
  934. # end of overwriting check
  935. fi
  936. if test -f fingerd.c -a "${1}" != "-c" ; then 
  937.   echo shar: Will not over-write existing file \"fingerd.c\"
  938. else
  939. echo shar: Extracting \"fingerd.c\" \(13848 characters\)
  940. sed "s/^X//" >fingerd.c <<'END_OF_fingerd.c'
  941. X/*
  942. X *    fingerd.c - finger server
  943. X *    Barry Shein/Phil Budne, Boston University
  944. X *
  945. X *    Should conform to RFC742 (which is a pretty vague thing)
  946. X *
  947. X *    Copyright (c) 1986, 1990 Barry Z. Shein & Philip L. Budne
  948. X */
  949. X
  950. X# ifndef lint
  951. Xstatic char *rcsid = "$Id: fingerd.c,v 3.0 90/07/06 13:10:44 budd Rel $";
  952. X# endif /* lint not defined */
  953. X
  954. X# include "finger.h"
  955. X
  956. X# include <stdio.h>
  957. X# include <sys/types.h>
  958. X# include <netinet/in.h>        /* sockaddr_in, IPPORT_FINGER */
  959. X# include <sys/socket.h>        /* AF_... */
  960. X# include <strings.h>            /* index */
  961. X# include <errno.h>            /* EINTR */
  962. X# include <pwd.h>            /* lookup nobody */
  963. X
  964. X# ifndef INETD
  965. X# include <sys/ioctl.h>            /* TIOCNOTTY */
  966. X# include <signal.h>            /* SIGCHLD */
  967. X# ifndef NO_WAIT_H
  968. X# include <sys/wait.h>            /* WNOHANG... */
  969. X# endif /* NO_WAIT_H not defined */
  970. X
  971. XFORWARD LOCAL void fireman();
  972. X# endif /* INETD not defined */
  973. X
  974. X/*
  975. X *    BZS - optional SYSLOG'ing of connections
  976. X */
  977. X# ifdef SYSLOG
  978. X# include <syslog.h>            /* LOG_... */
  979. X# include <netdb.h>            /* gethostbyaddr */
  980. X
  981. XFORWARD LOCAL void logit();
  982. X# endif /* SYSLOG defined */
  983. X
  984. X# ifdef USG
  985. X# define vfork fork
  986. X# endif /* USG defined */
  987. X
  988. X# ifndef MONNAME            /* ie SYSTEM:MONNAM.TXT */
  989. X# define MONNAME "/etc/monnam"        /* System name */
  990. X# endif /* MONNAME not defined */
  991. X
  992. X# ifndef NOLOGIN
  993. X# define NOLOGIN "/etc/nologin"
  994. X# endif /* NOLOGIN not defined */
  995. X
  996. X# define SERVICE "finger"        /* for getservent */
  997. X# define PROTOCOL "tcp"
  998. X
  999. X# ifndef IPPORT_FINGER            /* if services deficient */
  1000. X# define IPPORT_FINGER 79        /* usually in netinet/in.h */
  1001. X# endif /* IPPORT_FINGER not defined */
  1002. X
  1003. X# ifndef UID_NOBODY
  1004. X# define UID_NOBODY -2
  1005. X# endif /* UID_NOBODY not defined */
  1006. X
  1007. X# ifndef USER_NOBODY
  1008. X# define USER_NOBODY "nobody"
  1009. X# endif /* USER_NOBODY not defined */
  1010. X
  1011. X
  1012. X# define BACKLOG 5            /* max under 4.2 */
  1013. X
  1014. X/*
  1015. X *    Arbitrary...
  1016. X */
  1017. X# define MAXNAMES 100
  1018. X# define MAXHERALD 100
  1019. X
  1020. X/****************************************************************/
  1021. X
  1022. X# ifdef UTSNAME
  1023. X# include <sys/utsname.h>
  1024. X# else  /* UTSNAME not defined */
  1025. X
  1026. X/* perhaps ARCHITECTURE should be split into MFGR and MACHINE? */
  1027. X
  1028. X# ifdef sun
  1029. X# ifdef mc68010
  1030. X# define ARCHITECTURE "Sun-2"
  1031. X# endif /* mc68010 defined */
  1032. X# ifdef mc68020
  1033. X# define ARCHITECTURE "Sun-3"
  1034. X# endif /* mc68020 defined */
  1035. X# ifdef sparc
  1036. X# define ARCHITECTURE "Sun-4"
  1037. X# endif /* sparc defined */
  1038. X# ifdef i386
  1039. X# define ARCHITECTURE "Sun 386i"    /* "Road Runner"? */
  1040. X# endif /* i386 defined */
  1041. X# ifndef ARCHITECTURE
  1042. X# define ARCHITECTURE "Sun"
  1043. X# endif /* ARCHITECTURE not defined */
  1044. X# endif /* sun defined */
  1045. X
  1046. X# ifdef ibm032
  1047. X# define ARCHITECTURE "IBM ROMP"
  1048. X# endif /* ibm032 defined */
  1049. X
  1050. X# ifdef u3b
  1051. X# define ARCHITECTURE "AT&T 3B"
  1052. X# endif /* u3b defined */
  1053. X
  1054. X# ifdef u370
  1055. X# define ARCHITECTURE "IBM S/370"
  1056. X# endif /* u370 defined */
  1057. X
  1058. X# ifdef pdp11
  1059. X# define ARCHITECTURE "PDP-11"
  1060. X# endif /* pdp11 defined */
  1061. X
  1062. X# ifdef accel
  1063. X# define ARCHITECTURE "Celerity Accel"
  1064. X# endif /* accel defined */
  1065. X
  1066. X# ifndef ARCHITECTURE
  1067. X
  1068. X# ifdef vax
  1069. X# define ARCHITECTURE "VAX"
  1070. X# endif /* vax defined */
  1071. X
  1072. X# if defined(n16) || defined(ns32000) || defined(ns32032) || defined(ns32332)
  1073. X# define ARCHITECTURE "NS32k"
  1074. X# endif /* defined(n16) || defined(ns32000) || defined(ns32032) || defined(ns32332) */
  1075. X
  1076. X# ifdef mips
  1077. X# define ARCHITECTURE "MIPS"
  1078. X# endif /* mips defined */
  1079. X
  1080. X# ifdef sparc
  1081. X# define ARCHITECTURE "SPARC"
  1082. X# endif /* sparc defined */
  1083. X
  1084. X# if defined(mc68000) || defined(mc68020)
  1085. X# define ARCHITECTURE "MC68k"
  1086. X# endif /* defined(mc68000) || defined(mc68020) */
  1087. X
  1088. X# ifdef i386
  1089. X# define ARCHITECTURE "i386"
  1090. X# endif /* i386 defined */
  1091. X
  1092. X# endif /* ARCHITECTURE not defined */
  1093. X
  1094. X/****************************************************************/
  1095. X
  1096. X# ifdef bsd4_3
  1097. X# define DEFHERALD "4.3 BSD"
  1098. X# endif /* bsd4_3 defined */
  1099. X
  1100. X# if SunOS >= 400
  1101. X# define DEFHERALD "SunOS 4.0"        /* 4.1 has uname(2) */
  1102. X# endif /* SunOS >= 400 */
  1103. X
  1104. X# ifdef USG
  1105. X# define DEFHERALD "USG"
  1106. X# endif /* USG defined */
  1107. X
  1108. X# ifdef sequent
  1109. X# define DEFHERALD "Sequent Dynix"
  1110. X# endif /* sequent defined */
  1111. X
  1112. X# if Umax == 42
  1113. X# define DEFHERALD "Encore Umax 4.2"
  1114. X# endif /* Umax == 42 */
  1115. X
  1116. X# if Umax == 43
  1117. X# define DEFHERALD "Encore Umax 4.3"
  1118. X# endif /* Umax == 43 */
  1119. X
  1120. X# ifdef ultrix                /* Digital's big ideas */
  1121. X
  1122. X# define DEFHERALD "Ultrix"        /* Ultrix has uname(2) */
  1123. X# endif /* ultrix defined */
  1124. X
  1125. X# ifdef sony_news
  1126. X# define DEFHERALD "Sony NewsOS"
  1127. X# endif /* sony_news defined */
  1128. X
  1129. X# ifndef DEFHERALD            /* the default default herald!! */
  1130. X# define DEFHERALD "4.2 BSD"
  1131. X# endif /* DEFHERALD not defined */
  1132. X
  1133. X# endif /* UTSNAME not defined */
  1134. X
  1135. Xchar herald[MAXHERALD];
  1136. Xextern int errno, sys_nerr;
  1137. Xchar *sys_errlist[];
  1138. X
  1139. X/*
  1140. X *    Program we will fork to actually do the lookups
  1141. X */
  1142. Xchar *fingerpaths[] = {
  1143. X# ifdef FINGERPATHS
  1144. X    FINGERPATHS ,            /* alternate finger paths */
  1145. X# endif /* FINGERPATHS defined */
  1146. X    "/usr/local/bin/finger",
  1147. X    "/usr/local/finger",
  1148. X    "/usr/bin/finger",
  1149. X    "/usr/ucb/finger",
  1150. X
  1151. X    "/usr/local/bin/xf",
  1152. X    "/usr/local/xf",
  1153. X    "/usr/bin/xf",
  1154. X    "/usr/ucb/xf",
  1155. X
  1156. X    "/usr/ucb/w",
  1157. X    "/bin/who",
  1158. X    NULL
  1159. X};
  1160. X
  1161. X/* argv[0] for above
  1162. X# ifndef FINGER0
  1163. X# define FINGER0 "finger"
  1164. X# endif /* FINGER0 not defined */
  1165. X
  1166. X/*
  1167. X *    Program to print pretty hello message
  1168. X */
  1169. X
  1170. X# ifndef UPTIME
  1171. X# define UPTIME "/usr/ucb/uptime"    /* define this to print ldav, uptime */
  1172. X# endif /* UPTIME not defined */
  1173. X
  1174. X# ifndef UPTIME0
  1175. X# define UPTIME0 "uptime"
  1176. X# endif /* UPTIME0 not defined */
  1177. X
  1178. Xint debug;
  1179. X
  1180. XFORWARD LOCAL void Perror(), fperror(), iniherald(), doit(), pherald();
  1181. X
  1182. Xint main( argc, argv )
  1183. X    int argc;
  1184. X    char *argv[];
  1185. X{
  1186. X# ifdef INETD
  1187. X    iniherald();
  1188. X    doit( 0 );
  1189. X    exit( 0 );
  1190. X# else  /* INETD not defined */
  1191. X    int i, f;
  1192. X
  1193. X    iniherald();
  1194. X    /*
  1195. X     *    skip detaching the tty if first arg '-d'
  1196. X     */
  1197. X    if( (argc > 1)  && (argv[1][0] == '-') && (argv[1][1] == 'd'))
  1198. X    debug = 1;
  1199. X    else
  1200. X    debug = 0;
  1201. X
  1202. X    /*
  1203. X     *    After forking, child detaches controlling
  1204. X     *    terminal, parent exits, we are free
  1205. X     */
  1206. X    if( !debug ) {
  1207. X    switch( fork() ) {
  1208. X    case 0:                /* parent */
  1209. X        exit( 0 );
  1210. X
  1211. X    case -1:
  1212. X        Perror( "fork1" );
  1213. X    } /* switch */
  1214. X
  1215. X# ifdef USG
  1216. X    f = 32;                /* FIXME! */
  1217. X# else  /* USG not defined */
  1218. X    f = getdtablesize();
  1219. X# endif /* USG not defined */
  1220. X    for( i = 0; i < f; i++ )
  1221. X        (void) close( i );
  1222. X
  1223. X    /*
  1224. X     *    No one can hear you scream in space....
  1225. X     */
  1226. X    (void) open("/", 1);
  1227. X# ifdef USG                /* FIXME! */
  1228. X    (void) dup( 0 );
  1229. X    (void) dup( 0 );
  1230. X# else  /* USG not defined */
  1231. X    (void) dup2(0, 1);
  1232. X    (void) dup2(0, 2);
  1233. X# endif /* USG not defined */
  1234. X
  1235. X# ifdef TIOCNOTTY
  1236. X    if( (i = open("/dev/tty",2)) >= 0 ) {
  1237. X        (void) ioctl(i,TIOCNOTTY,0);
  1238. X        (void) close(i);
  1239. X    } /* tty open */
  1240. X# endif /* TIOCNOTTY defined */
  1241. X# ifdef USG
  1242. X    setpgrp();
  1243. X# endif /* USG defined */
  1244. X    } /* not debug */
  1245. X
  1246. X    signal(SIGCHLD, fireman);
  1247. X    f = getsocket();
  1248. X    listen(f,BACKLOG);
  1249. X    for( ; ; ) {
  1250. X    int  g, szfrom;
  1251. X    struct sockaddr_in from;
  1252. X
  1253. X    szfrom = sizeof( from );
  1254. X    if( (g = accept(f, &from, &szfrom)) < 0 ) {
  1255. X        if(errno != EINTR)
  1256. X        Perror("accept");
  1257. X        continue;
  1258. X    } /* accept */
  1259. X    switch( fork() ) {
  1260. X    case 0:
  1261. X        (void) close( f );
  1262. X        doit( g );
  1263. X        exit( 1 );            /* SHOULDNT HAPPEN */
  1264. X
  1265. X    case -1:
  1266. X        Perror( "fork2" );
  1267. X        break;
  1268. X    } /* fork switch */
  1269. X    (void) close(g);
  1270. X    } /* for ever */
  1271. X    /*NOTREACHED*/
  1272. X# endif /* INETD not defined */
  1273. X    return( 0 );            /* be ANSI, keep gcc quiet! */
  1274. X} /* main */
  1275. X
  1276. X/*
  1277. X *    doit -- forked to actually satisfy request
  1278. X */
  1279. XLOCAL void doit( s )
  1280. X    int s;
  1281. X{
  1282. X    char buf[BUFSIZ+1];
  1283. X    char *av[MAXNAMES+2], *ep[1];
  1284. X    register int i;
  1285. X    register char *bp, **pp;
  1286. X    int uid = UID_NOBODY;
  1287. X# ifdef USER_NOBODY
  1288. X    struct passwd *pw;
  1289. X# endif /* USER_NOBODY defined */
  1290. X        
  1291. X    (void) dup2( s, 1 );        /* dup socket onto stdout */
  1292. X    (void) dup2( s, 2 );        /* and stderr */
  1293. X    pherald();
  1294. X
  1295. X    /*
  1296. X     *    Note: this assumes request is sent in one shot
  1297. X     *    which is consistent with RFC742.
  1298. X     *
  1299. X     *  Never used gets() so never had worm hole!!
  1300. X     */
  1301. X    if( (i = read( s, buf, BUFSIZ)) < 0 )
  1302. X    fperror("could not read request");
  1303. X    buf[i] = EOS;            /* tie off buf */
  1304. X
  1305. X    /*
  1306. X     *    Make an argv list breaking at any space or ctrl chars
  1307. X     *    This is slightly more liberal than RFC742:
  1308. X     *        name,name,name is ok (RFC742)
  1309. X     *    so is
  1310. X     *        name name name
  1311. X     *    and by default things like:
  1312. X     *        name\nname\n
  1313. X     *        name\r\nname\r\n
  1314. X     */
  1315. X    i = 1;
  1316. X    bp = buf;
  1317. X    while( *bp != EOS ) {
  1318. X    while( (*bp <= ' ') || (*bp == ',') ) {
  1319. X        if(*bp == EOS)
  1320. X        break;
  1321. X        else
  1322. X        *bp = EOS;
  1323. X        bp++;
  1324. X    } /* while non print or comma */
  1325. X    if(*bp == EOS)
  1326. X        break;
  1327. X    av[i++] = bp;
  1328. X    if(i == MAXNAMES)
  1329. X        break;
  1330. X    while((*bp > ' ') && (*bp != ','))
  1331. X        bp++;
  1332. X    } /* while bp */
  1333. X    av[i] = NULL;            /* tie off argv */
  1334. X    ep[0] = NULL;            /* null environment */
  1335. X
  1336. X# ifdef SYSLOG
  1337. X    logit( s, av);
  1338. X# endif /* SYSLOG defined */
  1339. X
  1340. X# ifdef USER_NOBODY
  1341. X    if( (pw = getpwnam( USER_NOBODY )) != NULL )
  1342. X    uid = pw->pw_uid;
  1343. X# endif /* USER_NOBODY defined */
  1344. X    setuid( uid );            /* become noone --  so we are under */
  1345. X                    /* control of maxuprc */
  1346. X
  1347. X    for( pp = fingerpaths; *pp != NULL; pp++ ) {
  1348. X    av[0] = *pp;
  1349. X    execv(*pp, av);
  1350. X    } /* for fingerpaths */
  1351. X    /*
  1352. X     *    ERROR
  1353. X     */
  1354. X    puts("Could not find local finger program.");
  1355. X    fflush( stdout );
  1356. X# ifdef SYSLOG
  1357. X    syslog( LOG_ERR, "Could not find local finger program" );
  1358. X# endif /* SYSLOG defined */
  1359. X    _exit( 1 );
  1360. X} /* doit */
  1361. X
  1362. XLOCAL void pherald() {            /* print herald */
  1363. X    int fk;
  1364. X    FILE *fd;
  1365. X    char *ep[1];
  1366. X
  1367. X    ep[0] = NULL;
  1368. X    printf( "%s\r\n", herald );
  1369. X    fflush( stdout );
  1370. X
  1371. X# ifdef UPTIME
  1372. X    if( (fk = vfork()) == 0 ) {
  1373. X    execl(UPTIME, UPTIME0, 0 );
  1374. X    fperror(UPTIME);
  1375. X    }
  1376. X    else if( fk != -1 ) {
  1377. X    int wf;
  1378. X    while( (wf = wait(0)) != -1 && (wf != fk) )
  1379. X       ;
  1380. X    putchar( '\r' );        /* assume last char was \n */
  1381. X    }
  1382. X    else
  1383. X    Perror("fork3");
  1384. X# endif /* UPTIME defined */
  1385. X
  1386. X# ifdef NOLOGIN
  1387. X    if( (fd = fopen(NOLOGIN, "r")) != NULL ) {
  1388. X    register c, lc;
  1389. X
  1390. X    fputs( "\r\nNo Logins:\r\n", stdout );
  1391. X
  1392. X    lc = -1;            /* zap last char */
  1393. X    while( (c = getc( fd )) != EOF ) {
  1394. X        if( c == '\n' )
  1395. X        putchar( '\r' );
  1396. X        putchar( c );        /* output char */
  1397. X        lc = c;            /* save it */
  1398. X    } /* while */
  1399. X    fclose( fd );            /* close file */
  1400. X
  1401. X    if( lc != '\n' ) {        /* was last a newline? */
  1402. X        putchar( '\r' );
  1403. X        putchar( '\n' );        /* no, output one now */
  1404. X    }
  1405. X
  1406. X    /* WISH: perhaps print /etc/motd here too? */
  1407. X    } /* opened NOLOGIN */
  1408. X# endif /* NOLOGIN defined */
  1409. X
  1410. X    putchar( '\r' );
  1411. X    putchar( '\n' );            /* blank line */
  1412. X    fflush( stdout );
  1413. X} /* pherald */
  1414. X
  1415. XLOCAL void iniherald() {        /* create herald string once */
  1416. X    int f;
  1417. X    char namebuf[200];
  1418. X# ifdef UTSNAME
  1419. X    struct utsname uts;
  1420. X
  1421. X    uname( &uts );
  1422. X    strcpy( herald, uts.nodename );
  1423. X# else  /* UTSNAME not defined */
  1424. X    char myname[MAXHOSTLEN];
  1425. X
  1426. X    gethostname(myname, sizeof( myname ) );
  1427. X    strcpy(herald, myname );
  1428. X# endif /* UTSNAME not defined */
  1429. X    strcat(herald, " -- ");
  1430. X
  1431. X    if( (f = open(MONNAME, 0)) >= 0 &&
  1432. X       read(f, namebuf, sizeof( namebuf) -1 ) > 0 ) {
  1433. X    char *cp;
  1434. X
  1435. X    if( (cp = index(namebuf, '\n')) != NULL )
  1436. X        *cp = EOS;
  1437. X
  1438. X    strcat(herald, namebuf);
  1439. X    close( f );
  1440. X    } /* got MONNAME */
  1441. X    else {
  1442. X# ifdef UTSNAME
  1443. X    strcat(herald, uts.machine);
  1444. X    if( strcmp( uts.sysname, uts.nodename ) != 0 ) { /* SVR2?! */
  1445. X        strcat(herald, " " );
  1446. X        strcat(herald, uts.sysname );
  1447. X    }
  1448. X    strcat(herald, " release " );
  1449. X    strcat(herald, uts.release );
  1450. X# ifdef UmaxV
  1451. X    if( strcmp( uts.release, uts.version ) != 0 )
  1452. X# endif /* UmaxV defined */
  1453. X        strcat(herald, " version " ),
  1454. X        strcat(herald, uts.version );
  1455. X# else  /* UTSNAME not defined */
  1456. X    strcat(herald, DEFHERALD );
  1457. X# ifdef ARCHITECTURE
  1458. X    strcat(herald, " " );
  1459. X    strcat(herald, ARCHITECTURE );
  1460. X# endif /* ARCHITECTURE defined */
  1461. X# endif /* UTSNAME not defined */
  1462. X    } /* no MONNAME */
  1463. X} /* iniherald */
  1464. X
  1465. X# ifndef INETD
  1466. Xgetsocket() {
  1467. X    int f;
  1468. X    struct servent *sp;
  1469. X    struct sockaddr_in sin;
  1470. X      
  1471. X    bzero(&sin,sizeof sin);
  1472. X    sin.sin_family = AF_INET;
  1473. X
  1474. X    if( (sp = getservbyname( SERVICE, PROTOCOL )) == NULL)
  1475. X    sin.sin_port = sp->s_port;
  1476. X    else
  1477. X    sin.sin_port = htons( IPPORT_FINGER );
  1478. X
  1479. X    if( (f = socket(AF_INET,SOCK_STREAM,0)) < 0)
  1480. X    fperror("socket");
  1481. X
  1482. X    if(bind(f,(caddr_t)&sin,sizeof sin,0) < 0)
  1483. X    fperror("bind");
  1484. X
  1485. X    return( f );
  1486. X} /* getsocket */
  1487. X
  1488. XLOCAL void fireman() {            /* catch falling babies */
  1489. X# ifdef NO_WAIT_H
  1490. X    int w;
  1491. X
  1492. X    while( wait(&w) > 0 )
  1493. X    ;
  1494. X# else  /* NO_WAIT_H not defined */
  1495. X    union wait status;
  1496. X
  1497. X    while( wait3( &status, WNOHANG|WUNTRACED, 0) > 0 )
  1498. X    ;
  1499. X# endif /* NO_WAIT_H not defined */
  1500. X} /* catchchild */
  1501. X# endif /* INETD not defined */
  1502. X
  1503. X# ifdef SYSLOG
  1504. XLOCAL void logit(s, av)
  1505. X    int s;
  1506. X    register char **av;
  1507. X{
  1508. X    int i;
  1509. X    struct hostent *hp;
  1510. X    char buffer[ 1024 ];
  1511. X    struct sockaddr_in peer;
  1512. X    char *name, *inet_ntoa();
  1513. X
  1514. X    i = sizeof( peer );
  1515. X    if( getpeername( s, &peer, &i) != 0 )
  1516. X    return;
  1517. X
  1518. X# ifdef LOG_DAEMON
  1519. X    if( openlog( "fingerd", 0, LOG_DAEMON ) != 0 )
  1520. X    return;
  1521. X# else  /* LOG_DAEMON not defined */
  1522. X    if( openlog( "fingerd", 0) != 0 )
  1523. X    return;
  1524. X# endif /* LOG_DAEMON not defined */
  1525. X
  1526. X    hp = gethostbyaddr( (char *)&peer.sin_addr, sizeof(peer.sin_addr), AF_INET);
  1527. X    if( hp == NULL)
  1528. X    name = inet_ntoa( peer.sin_addr );
  1529. X    else
  1530. X    name = hp->h_name;
  1531. X
  1532. X    buffer[0] = EOS;
  1533. X    av++;                /* skip argv[0] */
  1534. X    while( *av != NULL ) {
  1535. X    if( buffer[0] != EOS )
  1536. X        strcat( buffer, " " );
  1537. X    strcat( buffer, *av++ );
  1538. X    } /* while av */
  1539. X
  1540. X    syslog( LOG_INFO, "%s: '%s'", name, buffer );
  1541. X} /* logit */
  1542. X# endif /* SYSLOG defined */
  1543. X
  1544. XLOCAL void Perror( s )            /* print error */
  1545. X    char *s;
  1546. X{
  1547. X# ifdef SYSLOG
  1548. X    syslog( LOG_ERR, "%s: %m", s );
  1549. X# endif /* SYSLOG defined */
  1550. X
  1551. X    if( errno < 1 || errno > sys_nerr )
  1552. X    fprintf( stderr, "fingerd: %s -- error %d\n", s, errno );
  1553. X    else
  1554. X    fprintf( stderr, "fingerd: %s -- %s\n", s, sys_errlist[ errno ] );
  1555. X} /* Perror */
  1556. X
  1557. XLOCAL void fperror( s )            /* fatal Perror */
  1558. X    char *s;
  1559. X{
  1560. X    Perror( s );
  1561. X    exit( 1 );
  1562. X}/* fperror */
  1563. X
  1564. X/*
  1565. X * Local variables:
  1566. X * comment-column: 40
  1567. X * End:
  1568. X */
  1569. END_OF_fingerd.c
  1570. if test 13848 -ne `wc -c <fingerd.c`; then
  1571.     echo shar: \"fingerd.c\" unpacked with wrong size!
  1572. fi
  1573. # end of overwriting check
  1574. fi
  1575. if test -f getcommand.c -a "${1}" != "-c" ; then 
  1576.   echo shar: Will not over-write existing file \"getcommand.c\"
  1577. else
  1578. echo shar: Extracting \"getcommand.c\" \(14997 characters\)
  1579. sed "s/^X//" >getcommand.c <<'END_OF_getcommand.c'
  1580. X/*
  1581. X * getcommand.c  -  return current command given a LUSER
  1582. X *
  1583. X * Copyright (C) 1986, 1990  Philip L. Budne
  1584. X *
  1585. X * This file is part of "Phil's Finger Program".
  1586. X *
  1587. X * This program is free software; you can redistribute it and/or modify
  1588. X * it under the terms of the GNU General Public License as published by
  1589. X * the Free Software Foundation; either version 1, or (at your option)
  1590. X * any later version.
  1591. X *
  1592. X */
  1593. X
  1594. X# ifndef lint
  1595. Xstatic char *rcsid = "$Id: getcommand.c,v 3.0 90/07/06 13:10:45 budd Rel $";
  1596. X# endif /* lint not defined */
  1597. X
  1598. X# include "finger.h"
  1599. X
  1600. X# ifndef Umax
  1601. X# include "ustruct.h"
  1602. X# else  /* Umax defined */
  1603. X# if Umax == 42
  1604. X# include <sys/signal.h>        /* for SIGxxx */
  1605. X# include <sys/pmdefs.h>        /* for SSTOP, procstates */
  1606. X# include <sys/time.h>            /* for statistics */
  1607. X# include <sys/types.h>            /* for dev_t */
  1608. X# include <sys/statistics.h>        /* for inq_stats */
  1609. X# include <sys/procstats.h>        /* for inq_stats */
  1610. X# endif /* Umax == 42 */
  1611. X# if Umax == 43
  1612. X# include <sys/signal.h>        /* for SIGxxx */
  1613. X# define KERNEL
  1614. X# include <sys/types.h>
  1615. X# undef KERNEL
  1616. X# include <sys/time.h>
  1617. X# include <sys/resource.h>
  1618. X# include <sys/proc.h>            /* Sxxx */
  1619. X# include <inq_stats/statistics.h>
  1620. X# include <inq_stats/procstats.h>
  1621. X# ifndef SSLEEP
  1622. X# define SSLEEP 1
  1623. X# endif /* SSLEEP not defined */
  1624. X# endif /* Umax == 43 */
  1625. X# endif /* Umax defined */
  1626. X
  1627. X# include <stdio.h>
  1628. X# include "args.h"            /* before luser.h */
  1629. X# include "luser.h"
  1630. X# include "pr.h"
  1631. X# include "daemon.h"
  1632. X# define WAITSTATENAME waitstatename    /* for waitstate.h */
  1633. X# include "waitstate.h"
  1634. X
  1635. X# ifdef Umax
  1636. X# include <sys/ioctl.h>            /* to get pgrp!!! */
  1637. X# define MAXP 100
  1638. XLOCAL struct pr prvec[ MAXP ];        /* per terminal process table */
  1639. X# else  /* Umax not defined */
  1640. X# include "kmem.h"
  1641. Xextern FTYPE kmem;            /* from kmem.c */
  1642. Xextern struct pr *readpr();        /* from readpr.c */
  1643. Xextern waitstate_t waitstate();        /* from readpr.c */
  1644. X
  1645. XLOCAL struct pr *prvec;            /* vector of processes */
  1646. XLOCAL int initialized;        /* true if have done readpr() */
  1647. X# endif /* Umax not defined */
  1648. X
  1649. X# if Umax != 42
  1650. XLOCAL char *procstates[] = {
  1651. X    "?0", "SL",
  1652. X# ifdef SVR3_STATES
  1653. X
  1654. X    "RU", "ZO", "ST", "ID", "ON", "SX",
  1655. X# ifdef UmaxV
  1656. X    "BS",
  1657. X# endif /* UmaxV defined */
  1658. X
  1659. X# else  /* SVR3_STATES not defined */
  1660. X
  1661. X    /* SVR2 and BSD */
  1662. X    "WA", "RU", "ID",
  1663. X# if Umax == 43
  1664. X    "ST", "EX", "EV",
  1665. X# else  /* not Umax == 43 */
  1666. X    "ZO", "ST",
  1667. X# ifdef AIX_RT
  1668. X    "?7", "?8", "?9", "SK",
  1669. X# endif /* AIX_RT defined */
  1670. X# endif /* not Umax == 43 */
  1671. X
  1672. X# endif /* SVR3_STATES not defined */
  1673. X    "**" };
  1674. X# endif /* Umax != 42 */
  1675. X
  1676. X# ifdef sun
  1677. Xextern dev_t consdev;
  1678. Xextern dev_t rconsdev;
  1679. Xextern dev_t dev_console;
  1680. X# endif /* sun defined */
  1681. X
  1682. X# ifndef PID_T
  1683. X# define PID_T short
  1684. X# endif /* PID_T not defined */
  1685. X
  1686. X# ifndef PID_BITS
  1687. X# define PID_BITS 15            /* most Unices only go up to 30000 */
  1688. X# endif /* PID_BITS not defined */
  1689. X
  1690. XLOCAL char *hidden[] = {
  1691. X# ifdef IN_DOT_SERVER
  1692. X    "in.comsat",
  1693. X    "in.syslog",
  1694. X    "in.talkd",
  1695. X    "in.rlogind",
  1696. X    "in.telnetd",
  1697. X# else  /* IN_DOT_SERVER not defined */
  1698. X    "comsat",
  1699. X    "syslogd",
  1700. X    "talkd",
  1701. X    "ntalkd",                /* 4.3 */
  1702. X    "rlogind",
  1703. X    "telnetd",
  1704. X# endif /* IN_DOT_SERVER not defined */
  1705. X# ifdef sun
  1706. X    "selection_svc",            /* SunView barfage */
  1707. X# endif /* sun defined */
  1708. X# ifdef HIDDEN_PROGRAMS
  1709. X    HIDDEN_PROGRAMS,
  1710. X# endif /* HIDDEN_PROGRAMS defined */
  1711. X    NULL
  1712. X};
  1713. X
  1714. XLOCAL struct pr *getcommand2();
  1715. X
  1716. X/*
  1717. X *    given a luser, return pr struct for executing command.
  1718. X *
  1719. X *    getcommand is a jacket for getcommand2 which finds the
  1720. X *    process.  we then trace back for process parent, and mark in
  1721. X *    luser struct for potential use in printing ttyloc.
  1722. X */
  1723. X
  1724. XGLOBAL struct pr *getcommand( u )
  1725. XLUSER *u;
  1726. X{
  1727. X    struct pr *p2, *lastpr;
  1728. X    register struct pr *pr;
  1729. X    PID_T pp;
  1730. X
  1731. X    u->u_command = u->u_daemonp = NULL;
  1732. X    u->u_daemon = NULL;
  1733. X
  1734. X    if( (p2 = getcommand2( u )) == NULL )
  1735. X    return( NULL );
  1736. X    u->u_command = p2;
  1737. X
  1738. X    /* only do this for lusers on ptys? *TODO* */
  1739. X    pp = p2->pr_ppid;
  1740. X    lastpr = NULL;
  1741. X    while( pp != INIT_PID && pp > 0 ) {
  1742. X    register struct daemon *dp;
  1743. X
  1744. X    for( pr = prvec; pr->pr_stat != 0; pr++ ) /* search process table */
  1745. X        if( pr->pr_pid == pp )    /* for parent process pid */
  1746. X        break;
  1747. X
  1748. X    if( pr->pr_pid != pp )        /* did not find parent? */
  1749. X        break;            /* (parent did not have a tty..) */
  1750. X
  1751. X    lastpr = pr;            /* save most 'recent' ancestor */
  1752. X    /* here with parent, check for daemon-ness */
  1753. X    for( dp = daemons; dp->d_cmd != NULL; dp++ )
  1754. X/*        printf("%d %s %s\n", pp, pr->pr_cmd, dp->d_cmd );/**/
  1755. X        if( pr->pr_cmd[0] == dp->d_cmd[0] && /* quick test */
  1756. X           strcmp( pr->pr_cmd, dp->d_cmd ) == 0 ) {
  1757. X        u->u_daemon = dp;    /* save daemon type */
  1758. X        u->u_daemonp = pr;    /* save process for kicks */
  1759. X        return( p2 );        /* need goto to leave 2 loops */
  1760. X        } /* daemon match */
  1761. X    pp = pr->pr_ppid;        /* keep moving up process tree */
  1762. X    } /* while dp */
  1763. X
  1764. X    /* catch things not in daemons[] */
  1765. X    /* (*) perhaps flush INIT_PID test? */
  1766. X    if( lastpr != NULL &&
  1767. X       pp == INIT_PID )            /* child of init (*) */
  1768. X    u->u_daemonp = lastpr;        /* save for possible display */
  1769. X    return( p2 );
  1770. X} /* getcommand */
  1771. X
  1772. X/*
  1773. X *    locate "current" process on a tty.
  1774. X *    requires many silly heuristics.
  1775. X */
  1776. X
  1777. XLOCAL struct pr *getcommand2( u )
  1778. X    LUSER *u;
  1779. X{
  1780. X    SIGNED long weight, topweight;
  1781. X    struct pr *topweightpr;
  1782. X    register struct pr *pp;        /* process pointer */
  1783. X    register PID_T curpid;
  1784. X    char **progs;
  1785. X    PID_T tpg;                /* this tty's process group */
  1786. X    dev_t ttyd;                /* tty device */
  1787. X
  1788. X# ifndef Umax
  1789. X    if( u->u_flags & U_BADTTY )
  1790. X    return( NULL );
  1791. X
  1792. X    if( !initialized ) {
  1793. X    initialized = TRUE;
  1794. X    prvec = readpr();        /* read process table once. */
  1795. X    } /* not initialized */
  1796. X
  1797. X    if( prvec == NULL )            /* have processes? */
  1798. X    return( NULL );
  1799. X
  1800. X    if( ISBADFILE( kmem ) )        /* have kernel memory? */
  1801. X    return( NULL );
  1802. X# endif /* Umax not defined */
  1803. X
  1804. X    tpg = -1;                /* terminal process group */
  1805. X    ttyd = u->u_ttydev;            /* get terminal device number */
  1806. X
  1807. X    topweight = MINUS_INF;
  1808. X    topweightpr = NULL;
  1809. X
  1810. X# ifdef sun
  1811. X    /*
  1812. X     * Sun console redirection (under SunOS 3.x and 4.0.3);
  1813. X     *
  1814. X     * values are major,minor
  1815. X     *                            consdev    rconsdev
  1816. X     * When the console device is the screen/kbd:    0,0(*)    0,0(*)
  1817. X     * When the console is serial port n:        12,n    12,n
  1818. X     * When the console is redirected to ptyN:        20,N    as above
  1819. X     *
  1820. X     * (*) under SunOS 4.0, 4.0.1 and 4.1 this is always 1,0
  1821. X     * but not under 4.0.3?!!
  1822. X     */
  1823. X
  1824. X# if SunOS >= 400 && SunOS != 403
  1825. X    if( ttyd == dev_console )        /* utter crockery */
  1826. X    ttyd = makedev(1,0);        /* seems to work! */
  1827. X# endif /* SunOS >= 400 && SunOS != 403 */
  1828. X
  1829. X    if( ttyd == dev_console &&        /* this is /dev/console */
  1830. X       consdev == rconsdev )        /* check if boot physical console */
  1831. X    ttyd = consdev;            /* is not screen, and not redirectd*/
  1832. X# endif /* sun defined */
  1833. X
  1834. X
  1835. X# ifdef Umax
  1836. X    ttyprocs( ttyd );            /* create array of processes on */
  1837. X                    /* this terminal */
  1838. X# endif /* Umax defined */
  1839. X
  1840. X# ifdef DEBUGSW
  1841. X    if( sw_debug )
  1842. X    printf("ttyd=%#x\n", ttyd );
  1843. X# endif /* DEBUGSW defined */
  1844. X
  1845. X    for( pp = prvec; pp->pr_stat != 0; pp++ ) {    /* for all processes */
  1846. X    if(
  1847. X# ifndef Umax
  1848. X       pp->pr_ttyp == NULL ||    /* no tty? */
  1849. X# endif /* Umax not defined */
  1850. X       ttyd != pp->pr_ttyd )    /* tty mismatch? */
  1851. X        continue;            /* yes, continue */
  1852. X
  1853. X# define ONE 8                /* do fixed point fractions */
  1854. X    weight = 0;
  1855. X    curpid = pp->pr_pid;
  1856. X
  1857. X    if( tpg == -1 )            /* try to get terminal */
  1858. X        tpg = gettpg( pp, u );    /*  process group */
  1859. X
  1860. X# ifdef Umax
  1861. X    switch( pp->pr_stat ) {
  1862. X    case SRUN:
  1863. X        if( pp->pr_wchan == 0 )
  1864. X        weight += ONE;
  1865. X        break;
  1866. X    case SWAIT:
  1867. X        weight += ONE;        /* some semaphore */
  1868. X        break;
  1869. X# ifndef SEVENT
  1870. X# define SEVENT (SEXEC+1)        /* in proc.h but not pmdefs.h */
  1871. X# endif /* SEVENT not defined */
  1872. X    case SEVENT:            /* some event wait.. */
  1873. X        weight += ONE / 2;
  1874. X        break;
  1875. X    } /* switch */
  1876. X# else  /* Umax not defined */
  1877. X    switch( waitstate( pp ) ) {
  1878. X    case WS_TI:
  1879. X        weight += ONE * 4;
  1880. X        break;
  1881. X    case WS_TO:
  1882. X        weight += ONE * 2;
  1883. X        break;
  1884. X    case WS_TW:            /* random terminal wait */
  1885. X    case WS_SE:            /* select */
  1886. X        weight += ONE / 2;
  1887. X        break;
  1888. X    case WS_RU:            /* no wait */
  1889. X        if( pp->pr_stat == SRUN )    /* runnable? */
  1890. X        weight += ONE;
  1891. X        break;
  1892. X    default:
  1893. X        break;
  1894. X    } /* case */
  1895. X# endif /* Umax not defined */
  1896. X
  1897. X/* sigh. give no special preference to leader (for things running under sh) */
  1898. X/*    if( curpid == tpg )        /* pid matches tty group? */
  1899. X/*        weight += ONE;        /* leader */
  1900. X
  1901. X/* give bonus to children of leader? What about ..grandchildren? *WISH* */
  1902. X/* (pp->pr_ppid == tpg ) */
  1903. X/* other ways to benefit by looking up parents?? (done in getcommand()) */
  1904. X
  1905. X    /* *WISH* perhaps consider p_pctcpu */
  1906. X
  1907. X    if( pp->pr_pgrp == tpg )    /* process in process group? */
  1908. X        weight += ONE;
  1909. X
  1910. X    if( pp->pr_stat == SSTOP )    /* stopped? */
  1911. X        weight -= ONE / 2;
  1912. X
  1913. X    if( pp->pr_ppid == INIT_PID )    /* child of init? */
  1914. X        weight -= ONE / 2;
  1915. X
  1916. X    if( pp->pr_pgrp == 0 )        /* no process group? */
  1917. X        weight -= ONE / 4;
  1918. X
  1919. X# ifdef SLOAD
  1920. X    if( (pp->pr_flag & SLOAD) == 0 ) /* swapped? */
  1921. X        weight -= ONE / 4;
  1922. X# endif /* SLOAD defined */
  1923. X
  1924. X    /* this is to catch programs started by sh with '&' */
  1925. X    if( pp->pr_intr == S_IGNORE && pp->pr_quit == S_IGNORE )
  1926. X        weight -= ONE / 4;
  1927. X
  1928. X    if( pp->pr_hup == S_IGNORE )    /* process is nohup? */
  1929. X        weight -= ONE / 4;        /* was once 1/8th */
  1930. X
  1931. X    /*
  1932. X     * penalize ugly stuff like "gamescontrol" which
  1933. X     * tend to have high pids.
  1934. X     */
  1935. X    for( progs = hidden; *progs != NULL; progs++ )
  1936. X        if( strcmp( pp->pr_cmd, *progs ) == 0 ) {
  1937. X        weight -= ONE;
  1938. X        break;
  1939. X        }
  1940. X
  1941. X    pp->pr_weight = weight = (weight<<PID_BITS)/ONE + curpid;
  1942. X    if( weight > topweight ) {    /* beat previous winner */
  1943. X        topweight = weight;
  1944. X        topweightpr = pp;
  1945. X    } /* beat winner */
  1946. X
  1947. X# ifdef DEBUGSW
  1948. X    if( sw_debug )
  1949. X        dumppr( pp );
  1950. X# endif /* DEBUGSW defined */
  1951. X
  1952. X    } /* for pp */
  1953. X
  1954. X    return( topweightpr );
  1955. X} /* getcommand2 */
  1956. X
  1957. X# ifdef Umax
  1958. XLOCAL ttyprocs( dev )            /* get pr's for this terminal */
  1959. X    dev_t dev;
  1960. X{
  1961. X    struct stat_descr sd;
  1962. X    register int i;
  1963. X    register struct pr *pp;
  1964. X    register struct proc_detail *pd;
  1965. X    struct proc_detail dd[ MAXP ];
  1966. X
  1967. X    sd.sd_next     = NULL;
  1968. X    sd.sd_objid    = dev;
  1969. X    sd.sd_subsys   = SUBSYS_PROC;
  1970. X    sd.sd_type     = PROCTYPE_DETAIL;
  1971. X    sd.sd_options  = PROC_DETAIL_TERM | PROC_DETAIL_GLEADER;
  1972. X    sd.sd_addr     = (char *) dd;    /* point to data region */
  1973. X    sd.sd_size     = sizeof( dd );    /* give size */
  1974. X    sd.sd_sizeused = 0;
  1975. X  
  1976. X    if( inq_stats(1, &sd) != 0 ) {
  1977. X    perror("inq_stats");
  1978. X    exit(1);
  1979. X    }
  1980. X
  1981. X# define SZ sizeof( struct proc_detail )
  1982. X    pp = prvec;
  1983. X    pd = dd;
  1984. X    for( i = sd.sd_sizeused; i >= SZ; i -= SZ ) {
  1985. X    pp->pr_pid  = pd->pd_pid;
  1986. X    pp->pr_ppid = pd->pd_ppid;
  1987. X    pp->pr_pgrp = pd->pd_pgrp;
  1988. X    pp->pr_uid  = pd->pd_uid;
  1989. X    pp->pr_flag = pd->pd_flag;
  1990. X    pp->pr_stat = pd->pd_state;
  1991. X    pp->pr_ttyd = dev;
  1992. X    strncpy(pp->pr_cmd, pd->pd_command, sizeof( pp->pr_cmd ) );
  1993. X# define SIGFIG(pd,s) ( (pd->pd_sigignore & (1<<(s))) ? S_IGNORE : \
  1994. X                (pd->pd_sigcatch  & (1<<(s))) ? S_CATCH  : S_DEFAULT )
  1995. X    pp->pr_hup  = SIGFIG(pd,SIGHUP);
  1996. X    pp->pr_intr = SIGFIG(pd,SIGINT);
  1997. X    pp->pr_quit = SIGFIG(pd,SIGQUIT);
  1998. X# undef SIGFIG
  1999. X    pp->pr_wchan = (caddr_t) pd->pd_sem; /* why not? */
  2000. X                    /* no way to figure out what */
  2001. X                    /* EVENT is what tho... */
  2002. X    pd++;
  2003. X    pp++;
  2004. X    } /* while i */
  2005. X    pp->pr_stat = 0;            /* mark end */
  2006. X} /* ttyprocs */
  2007. X# endif /* Umax defined */
  2008. X
  2009. XGLOBAL void
  2010. Xdumppr( pp )
  2011. X    register struct pr *pp;
  2012. X{
  2013. X    int st;
  2014. X    waitstate_t s;
  2015. X
  2016. X    st = pp->pr_stat;
  2017. X    if( st < 0 || st > sizeof( procstates ) - 1 )
  2018. X    st = 0;
  2019. X# ifdef Umax
  2020. X    s = WS_SL;
  2021. X# else  /* Umax not defined */
  2022. X    s = waitstate( pp );
  2023. X# endif /* Umax not defined */
  2024. X    printf("%6dp %6dpp %6dpg %2s %2s %ci %cq %ch %5du %#8x %s %s %d\n",
  2025. X       pp->pr_pid,
  2026. X       pp->pr_ppid,
  2027. X       pp->pr_pgrp,
  2028. X       procstates[ st ],
  2029. X# if defined(SLOAD) && !defined(UmaxV)
  2030. X       ( (pp->pr_flag & SLOAD) ? "" : "SW" ),
  2031. X# else  /* not defined(SLOAD) && !defined(UmaxV) */
  2032. X       "",
  2033. X# endif /* not defined(SLOAD) && !defined(UmaxV) */
  2034. X       SIGNAME[ (int) pp->pr_intr ],
  2035. X       SIGNAME[ (int) pp->pr_quit ],
  2036. X       SIGNAME[ (int) pp->pr_hup  ],
  2037. X       pp->pr_uid,
  2038. X       pp->pr_ttyd,
  2039. X# if Umax == 42
  2040. X       "",                /* always bogus */
  2041. X# else  /* not Umax == 42 */
  2042. X       WAITSTATENAME[ (int)s ],
  2043. X# endif /* not Umax == 42 */
  2044. X       pp->pr_cmd,
  2045. X       pp->pr_weight
  2046. X       );
  2047. X} /* dumppr */
  2048. X
  2049. XGLOBAL int gettpg( pp, u )
  2050. Xregister struct pr *pp;
  2051. XLUSER *u;
  2052. X{
  2053. X    short tpg;                /* MUST BE SHORT! (for SHORT_TTYP) */
  2054. X# ifdef Umax
  2055. X    static int checked = FALSE, notty = FALSE;
  2056. X    int f, w;
  2057. X    char devn[ 30 ];
  2058. X
  2059. X    /* inq_stats does has no way to get terminal process group.  Newer
  2060. X     * releases have /dev/kmem, but rather than have to deal with kmem
  2061. X     * at all we open the tty (for write!) and do the ioctl!  if users
  2062. X     * do "mesg n" finger has to run suid root to ensure access (it is
  2063. X     * safe to do so)! (see BUGS in man page)
  2064. X     */
  2065. X    strcpy( devn, "/dev/" );
  2066. X    strcat( devn, u->u_line );
  2067. X
  2068. X    if( !checked ) {            /* check if we have a tty */
  2069. X    if( (f = open( "/dev/tty", 1)) >= 0 )
  2070. X        close( f );            /* yes we do */
  2071. X    else
  2072. X        notty = TRUE;        /* we don't */
  2073. X    checked = TRUE;
  2074. X    }
  2075. X
  2076. X    tpg = -2;
  2077. X    if( (f = open( devn, 1 )) >= 0 ) {    /* open for write!! */
  2078. X    if( ioctl( f, TIOCGPGRP, &w ) == 0 ) /* to get pgrp!!! */
  2079. X        tpg = w;
  2080. X    close( f );
  2081. X
  2082. X    /* flush tty association -- so fingerd doesn't get attached!! */
  2083. X    if( notty && (f = open( "/dev/tty", 1)) >= 0 ) { /* if no tty */
  2084. X        ioctl( f, TIOCNOTTY, 0 );    /* flush assoc with one */
  2085. X        close( f );            /* we just opened */
  2086. X    }
  2087. X    }
  2088. X# else  /* Umax not defined */
  2089. X# ifndef AIX3
  2090. X# ifdef SHORT_TTYP
  2091. X    /* ttyp is pointer to (short) process group in stream structure! */
  2092. X    if( ! KMEMREAD( (long)pp->pr_ttyp, (char *)&tpg, sizeof(tpg)) )
  2093. X    tpg = -2;
  2094. X# else  /* SHORT_TTYP not defined */
  2095. X    /* read just process group from tty struct */
  2096. X    if( ! KMEMREAD( (long)&pp->pr_ttyp->t_pgrp, (char *)&tpg, sizeof(tpg)) )
  2097. X    tpg = -2;
  2098. X# endif /* SHORT_TTYP not defined */
  2099. X# endif /* AIX3 not defined */
  2100. X# endif /* Umax not defined */
  2101. X# ifdef DEBUGSW
  2102. X    if( sw_debug )
  2103. X        printf("tpg=%d\n", tpg );
  2104. X# endif /* DEBUGSW defined */
  2105. X    return( tpg );
  2106. X} /* gettpg */
  2107. X
  2108. XGLOBAL void
  2109. Xgetstate( bp, pp )
  2110. X    char *bp;
  2111. X    struct pr *pp;
  2112. X{
  2113. X    waitstate_t s;
  2114. X    int st;
  2115. X
  2116. X    st = pp->pr_stat;
  2117. X    if( st < 0 || st > sizeof( procstates ) - 1 )
  2118. X    st = 0;
  2119. X
  2120. X# ifdef Umax
  2121. X# if Umax == 42
  2122. X    bp[0] = procstates[st][0];
  2123. X    bp[1] = procstates[st][1];
  2124. X    bp[2] = procstates[st][2];
  2125. X    bp[3] = procstates[st][3];
  2126. X# endif /* Umax == 42 */
  2127. X# else  /* Umax not defined */
  2128. X    if( st == SSLEEP ) {
  2129. X    s = waitstate( pp );
  2130. X    bp[0] = WAITSTATENAME[ (int)s ][0];
  2131. X    bp[1] = WAITSTATENAME[ (int)s ][1];
  2132. X    }
  2133. X    else {
  2134. X    bp[0] = procstates[st][0];
  2135. X    bp[1] = procstates[st][1];
  2136. X    }
  2137. X
  2138. X    bp[2] = bp[3] = ' ';
  2139. X# if defined(SLOAD) && !defined(UmaxV)
  2140. X    if( (pp->pr_flag & SLOAD) == 0 ) {
  2141. X    bp[2] = 'S';
  2142. X    bp[3] = 'W';
  2143. X    }
  2144. X# endif /* defined(SLOAD) && !defined(UmaxV) */
  2145. X# endif /* Umax not defined */
  2146. X    bp[4] = EOS;
  2147. X
  2148. X} /* getstate */
  2149. X
  2150. X/*
  2151. X * Local variables:
  2152. X * comment-column: 40
  2153. X * End:
  2154. X */
  2155. END_OF_getcommand.c
  2156. if test 14997 -ne `wc -c <getcommand.c`; then
  2157.     echo shar: \"getcommand.c\" unpacked with wrong size!
  2158. fi
  2159. # end of overwriting check
  2160. fi
  2161. echo shar: End of archive 6 \(of 7\).
  2162. cp /dev/null ark6isdone
  2163. MISSING=""
  2164. for I in 1 2 3 4 5 6 7 ; do
  2165.     if test ! -f ark${I}isdone ; then
  2166.     MISSING="${MISSING} ${I}"
  2167.     fi
  2168. done
  2169. if test "${MISSING}" = "" ; then
  2170.     echo You have unpacked all 7 archives.
  2171.     rm -f ark[1-9]isdone
  2172. else
  2173.     echo You still need to unpack the following archives:
  2174.     echo "        " ${MISSING}
  2175. fi
  2176. ##  End of shell archive.
  2177. exit 0
  2178.  
  2179.